package com.zbs.framework.common.utils;

import com.google.common.base.CaseFormat;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public final class DateUtils {
    /**
     * 英文简写（默认）如：2010-12-01
     */
    public static String FORMAT_SHORT = "yyyy-MM-dd";
    /**
     * 英文简写（默认）如：2010-12-01
     */
    public static String FORMAT_DIY = "yyyy/MM/dd";

    /**
     * 英文全称  如：2010-12-01 23:15:06
     */
    public static String FORMAT_LONG = "yyyy-MM-dd HH:mm:ss";

    /**
     * 精确到毫秒的完整时间    如：yyyy-MM-dd HH:mm:ss.S
     */
    public static String FORMAT_FULL = "yyyy-MM-dd HH:mm:ss.S";

    /**
     * 中文简写  如：2010年12月01日
     */
    public static String FORMAT_SHORT_CN = "yyyy年MM月dd";

    /**
     * 中文全称  如：2010年12月01日  23时15分06秒
     */
    public static String FORMAT_LONG_CN = "yyyy年MM月dd日  HH时mm分ss秒";

    /**
     * 精确到毫秒的完整中文时间
     */
    public static String FORMAT_FULL_CN = "yyyy年MM月dd日  HH时mm分ss秒SSS毫秒";

    /**
     * 获得默认的 date pattern
     */
    public static String getDatePattern() {
        return FORMAT_LONG;
    }

    /**
     * 获得默认的 date
     */
    public static String getDatePatt() {
        return FORMAT_DIY;
    }

    public static String getDateShot() {
        return FORMAT_SHORT;
    }

    /**
     * 根据预设格式返回当前日期
     *
     * @return
     */
    public static String getNow() {
        return format(new Date());
    }

    public static Date getDate() {
        return new Date();
    }

    public static Date getDate(String format) {
        return parse(getNow(format), format);
    }

    /**
     * 根据用户格式返回当前日期
     *
     * @param format
     * @return
     */
    public static String getNow(String format) {
        return format(new Date(), format);
    }


    /**
     * 使用预设格式格式化日期
     *
     * @param date
     * @return
     */
    public static String format(Date date) {
        return format(date, getDatePattern());
    }

    /**
     * 使用预设格式格式化日期
     *
     * @param date
     * @return
     */
    public static String format1(Date date) {
        return format(date, getDatePatt());
    }

    public static String format2(Date date) {
        return format(date, getDateShot());
    }

    /**
     * 使用用户格式格式化日期
     *
     * @param date    日期
     * @param pattern 日期格式
     * @return
     */
    public static String format(Date date, String pattern) {
        String returnValue = "";
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            returnValue = df.format(date);
        }
        return (returnValue);
    }

    /**
     * 使用预设格式提取字符串日期
     *
     * @param strDate 日期字符串
     * @return
     */
    public static Date parse(String strDate) {
        StringBuilder stringBuilder = new StringBuilder(strDate);
        if (strDate.length() == 10) {
            stringBuilder.append(" 00:00:00");
        }
        return parse(stringBuilder.toString(), getDatePattern());
    }

    public static Date parseShot(String strDate) {
        StringBuilder stringBuilder = new StringBuilder(strDate);
        if (strDate.length() == 10) {
            stringBuilder.append(" 00:00:00");
        }
        return parse(stringBuilder.toString(), getDateShot());
    }

    /**
     * 使用用户格式提取字符串日期
     *
     * @param strDate 日期字符串
     * @param pattern 日期格式
     * @return
     */
    public static Date parse(String strDate, String pattern) {
        SimpleDateFormat df = new SimpleDateFormat(pattern);
        try {
            return df.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Date parse(Date date, String pattern) {
        return parse(format(date, pattern) + " 00:00:00");
    }

    /**
     * 在日期上增加数个整月
     *
     * @param date 日期
     * @param n    要增加的月数
     * @return
     */
    public static Date addMonth(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, n);
        return cal.getTime();
    }

    /**
     * 在日期上增加天数
     *
     * @param date 日期
     * @param n    要增加的天数
     * @return
     */
    public static Date addDay(Date date, int n) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, n);
        return cal.getTime();
    }

    /**
     * 在日期上增加天数
     *
     * @param dateStr 日期
     * @param n       要增加的天数
     * @return
     */
    public static String addDay(String dateStr, int n) {
        Date date = parse(dateStr);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, n);
        return format(cal.getTime());
    }

    /**
     * 获取时间戳
     */
    public static String getTimeString() {
        SimpleDateFormat df = new SimpleDateFormat(FORMAT_FULL);
        Calendar calendar = Calendar.getInstance();
        return df.format(calendar.getTime());
    }

    /**
     * 获取日期年份
     *
     * @param date 日期
     * @return
     */
    public static String getYear(Date date) {
        return format(date).substring(0, 4);
    }

    /**
     * 按默认格式的字符串距离今天的天数
     *
     * @param date 日期字符串
     * @return
     */
    public static int countDays(String date) {
        long t = Calendar.getInstance().getTime().getTime();
        Calendar c = Calendar.getInstance();
        c.setTime(parse(date));
        long t1 = c.getTime().getTime();
        return (int) (t / 1000 - t1 / 1000) / 3600 / 24;
    }

//    /**
//     * 按用户格式字符串距离今天的天数
//     * @param date 日期字符串
//     * @param format 日期格式
//     * @return
//     */
//    public static int countDays (String date, String format) {
//        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(Objects.requireNonNull(parse(getNow(), FORMAT_SHORT)));
//        long t = calendar.getTime().getTime();
//
//        Calendar c = Calendar.getInstance();
//        c.setTime(Objects.requireNonNull(parse(date, format)));
//        long t1 = c.getTime().getTime();
//        return (int)(t/1000 - t1/1000)/3600/24;
//    }

    /**
     * @param @param  timestr
     * @param @return 设定文件
     * @return Date    返回类型
     * @throws
     * @Title: getBackTime
     * @Description:
     */
    public static Date getBackTime(String timestr) {
        Date curTime = new Date();
        Date startTime = DateUtils.addMonth(curTime, -12);
        if (timestr.equals("ONEYEAE")) {
        } else if (timestr.equals("TWOYEAR")) {
            startTime = DateUtils.addMonth(curTime, -12 * 2);
        } else if (timestr.equals("ALL")) {
            startTime = null;
        }
        return startTime;
    }

    /**
     * 获取当前日期是星期几<br>
     *
     * @param date
     * @return 当前日期是星期几
     */
    public Integer getWeekOfDate(Date date) {
        Integer[] weekDays = {7, 1, 2, 3, 4, 5, 6};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }

    /**
     * 计算时间差
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static int countDays(Date startDate, Date endDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        long t = calendar.getTime().getTime();

        Calendar c = Calendar.getInstance();
        c.setTime(startDate);
        long t1 = c.getTime().getTime();
        return (int) (t / 1000 - t1 / 1000) / 3600 / 24;
    }

    public static int countDays(String startDateStr, String endDateStr) {
        Date startDate = parse(startDateStr);
        Date endDate = parse(endDateStr);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        long t = calendar.getTime().getTime();

        Calendar c = Calendar.getInstance();
        c.setTime(startDate);
        long t1 = c.getTime().getTime();
        return (int) (t / 1000 - t1 / 1000) / 3600 / 24;
    }

    /**
     * 获取年月日的时间
     *
     * @param date
     * @return
     */
    public static Date getEndTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 时
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        // 分
        calendar.set(Calendar.MINUTE, 59);
        // 秒
        calendar.set(Calendar.SECOND, 59);
        // 毫秒
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Date getEndTime(Date date, String format) {
        return getEndTime(parse(date, format));
    }

    public static Date getEndTime(String date, String format) {
        return getEndTime(parse(date, format));
    }

    public static Date getEndTime(String date) {
        return getEndTime(parse(date));
    }

    public static String getEndTimeStr(String date) {
        return format(getEndTime(parse(date)));
    }

    public static String getEndTimeStr(Date date) {
        return format(getEndTime(date));
    }

    public static String getEndTimeStr(Date date, String format) {
        return format(getEndTime(date), format);
    }

    public static Date getStartTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 时
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 分
        calendar.set(Calendar.MINUTE, 0);
        // 秒
        calendar.set(Calendar.SECOND, 0);
        // 毫秒
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Date getStartTime(Date date, String format) {
        return getStartTime(parse(date, format));
    }

    public static Date getStartTime(String date, String format) {
        return getStartTime(parse(date, format));
    }

    public static Date getStartTime(String date) {
        return getStartTime(parse(date));
    }

    public static String getStartTimeStr(String date) {
        return format(getStartTime(parse(date)));
    }

    public static String getStartTimeStr(Date date) {
        return format(getStartTime(date));
    }

    public static String getStartTimeStr(Date date, String format) {
        return format(getStartTime(date), format);
    }

    /*
     * 0 指前面补充零
     * formatLength 字符总长度为 formatLength
     * d 代表为正数。
     */
    public static String frontCompWithZero(Long sourceDate, int formatLength) {
        return String.format("%0" + formatLength + "d", sourceDate);
    }

    /**
     * 获取本月第一天
     *
     * @return
     */
    public static Date getMonthMinDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

    /**
     * 获取本月最后一天
     *
     * @return
     */
    public static Date getMonthMaxDate() {
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(new Date());
        calendar2.set(Calendar.DAY_OF_MONTH, calendar2.getActualMaximum(Calendar.DAY_OF_MONTH));
        return getEndTime(calendar2.getTime());
    }

    /**
     * 驼峰式的实体类属性名转换为数据表字段名
     *
     * @param camelCaseStr 驼峰式的实体类属性名
     * @return 转换后的以"_"分隔的数据表字段名
     */
    public static String decamelize(String camelCaseStr) {
//        Pattern humpPattern = Pattern.compile("[A-Z]");
//        Matcher matcher = humpPattern.matcher(camelCaseStr);
//        StringBuffer sb = new StringBuffer();
//        while (matcher.find()) {
//            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
//        }
//        matcher.appendTail(sb);
//        final String str = sb.toString();
//        if (str.charAt(0) == '_'){
//            return str.substring(1);
//        }
//        return str;

        return !StringUtils.hasLength(camelCaseStr) ? "" : CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, camelCaseStr);
    }

    public static String camelCaseNameByClassName(String decamelize) {
        return !StringUtils.hasLength(decamelize) ? "" : CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, decamelize);
    }

    public static String camelCaseNameByPropertyName(String decamelize) {
        return !StringUtils.hasLength(decamelize) ? "" : CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, decamelize);
    }


    /**
     * 字符串是否为空
     *
     * @param cs 待检查的字符串
     * @return 空：true; 非空：false
     */
    public static boolean isBlank(final CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    public static Map<String, Object> checkParams(Map<String, Object> oldParams) {
        Map<String, Object> params = new HashMap<>();
        oldParams.keySet().forEach(key -> {
            if (!ObjectUtils.isEmpty(oldParams.get(key))) {
                params.put(key, oldParams.get(key));
            }
        });
        return params;
    }

    /**
     * 将对象装换为map
     *
     * @param bean
     * @return
     */
    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = Maps.newHashMap();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key + "", beanMap.get(key));
            }
        }
        return map;
    }

    /**
     * 将map装换为javabean对象
     *
     * @param map
     * @param bean
     * @return
     */
    public static <T> T mapToBean(Map<String, Object> map, T bean) {
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    }

    /**
     * 将List<T>转换为List<Map<String, Object>>
     *
     * @param objList
     * @return
     */
    public static <T> List<Map<String, Object>> objectsToMaps(List<T> objList) {
        List<Map<String, Object>> list = Lists.newArrayList();
        if (objList != null && objList.size() > 0) {
            Map<String, Object> map = null;
            T bean = null;
            for (int i = 0, size = objList.size(); i < size; i++) {
                bean = objList.get(i);
                map = beanToMap(bean);
                list.add(map);
            }
        }
        return list;
    }


}